﻿using DBUtil.MetaData;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace DBUtil.Provider.SqlServer.MetaData
{
    /// <summary>
    /// SqlServer列
    /// </summary>
    public class SqlServerColumn : Column
    {
        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.ORDINAL_POSITION
        /// </summary>
        public string ORDINAL_POSITION { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.DATA_TYPE
        /// </summary>
        public string DATA_TYPE { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.CHARACTER_MAXIMUM_LENGTH
        /// </summary>
        public string CHARACTER_MAXIMUM_LENGTH { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_PRECISION
        /// </summary>
        public string NUMERIC_PRECISION { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_PRECISION_RADIX
        /// </summary>
        public string NUMERIC_PRECISION_RADIX { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.NUMERIC_SCALE
        /// </summary>
        public string NUMERIC_SCALE { internal set; get; }

        /// <summary>
        /// INFORMATION_SCHEMA.COLUMNS.DATETIME_PRECISION
        /// </summary>
        public string DATETIME_PRECISION { internal set; get; }

        #region ConvertType 转换列类型
        internal void ConvertType()
        {
            var column = this;
            var type = DATA_TYPE;
            var maxLen = CHARACTER_MAXIMUM_LENGTH;
            var datetime_precision = DATETIME_PRECISION;
            var number_precision = NUMERIC_PRECISION;
            var number_scale = NUMERIC_SCALE;
            switch (type)
            {
                case "bigint":
                    {
                        column.Type = EnumColumnType.Long;
                        column.TypeString = "bigint";
                        break;
                    }
                case "binary":
                    {
                        column.Type = EnumColumnType.Blob;
                        column.TypeString = $"binary({maxLen})";
                        break;
                    }
                case "bit":
                    {
                        column.Type = EnumColumnType.Bit;
                        column.TypeString = $"bit";
                        break;
                    }
                case "char":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"char({maxLen})";
                        break;
                    }
                case "date":
                    {
                        column.Type = EnumColumnType.Date;
                        column.TypeString = $"date";
                        break;
                    }
                case "datetime":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"datetime";
                        break;
                    }
                case "datetime2":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"datetime2({datetime_precision})";
                        break;
                    }
                case "datetimeoffset":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"datetimeoffset({datetime_precision})";
                        break;
                    }
                case "decimal":
                    {
                        column.Type = EnumColumnType.Decimal;
                        column.TypeString = $"decimal({number_precision},{number_scale})";
                        break;
                    }
                case "float":
                    {
                        column.Type = EnumColumnType.Float;
                        column.TypeString = $"float";
                        break;
                    }
                case "geography":
                    {
                        column.Type = EnumColumnType.Other;
                        column.TypeString = $"geography";
                        break;
                    }
                case "geometry":
                    {
                        column.Type = EnumColumnType.Other;
                        column.TypeString = $"geometry";
                        break;
                    }
                case "hierarchyid":
                    {
                        column.Type = EnumColumnType.Other;
                        column.TypeString = $"hierarchyid";
                        break;
                    }
                case "image":
                    {
                        column.Type = EnumColumnType.Blob;
                        column.TypeString = $"image";
                        break;
                    }
                case "int":
                    {
                        column.Type = EnumColumnType.Int;
                        column.TypeString = $"int";
                        break;
                    }
                case "money":
                    {
                        column.Type = EnumColumnType.Double;
                        column.TypeString = $"money";
                        break;
                    }
                case "nchar":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"nchar({maxLen})";
                        break;
                    }
                case "ntext":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"ntext";
                        break;
                    }
                case "numeric":
                    {
                        column.Type = EnumColumnType.Double;
                        column.TypeString = $"numeric({number_precision},{number_scale})";
                        break;
                    }
                case "nvarchar":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"nvarchar({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"nvarchar(max)";
                        }
                        break;
                    }
                case "real":
                    {
                        column.Type = EnumColumnType.Double;
                        column.TypeString = $"real";
                        break;
                    }
                case "smalldatetime":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"smalldatetime";
                        break;
                    }
                case "smallint":
                    {
                        column.Type = EnumColumnType.Int;
                        column.TypeString = $"smallint";
                        break;
                    }
                case "smallmoney":
                    {
                        column.Type = EnumColumnType.Double;
                        column.TypeString = $"smallmoney";
                        break;
                    }
                case "sql_variant":
                    {
                        column.Type = EnumColumnType.Other;
                        column.TypeString = $"sql_variant";
                        break;
                    }
                case "text":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"text";
                        break;
                    }
                case "time":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"time({datetime_precision})";
                        break;
                    }
                case "timestamp":
                    {
                        column.Type = EnumColumnType.DateTime;
                        column.TypeString = $"timestamp";
                        break;
                    }
                case "tinyint":
                    {
                        column.Type = EnumColumnType.Int;
                        column.TypeString = $"tinyint";
                        break;
                    }
                case "uniqueidentifier":
                    {
                        column.Type = EnumColumnType.Other;
                        column.TypeString = $"uniqueidentifier";
                        break;
                    }
                case "varbinary":
                    {
                        column.Type = EnumColumnType.Blob;
                        column.TypeString = $"varbinary({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"varbinary(max)";
                        }
                        break;
                    }
                case "varchar":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"varchar({maxLen})";
                        if (maxLen == "-1")
                        {
                            column.TypeString = $"varchar(max)";
                        }
                        break;
                    }
                case "xml":
                    {
                        column.Type = EnumColumnType.String;
                        column.TypeString = $"xml";
                        break;
                    }
            }
        }
        #endregion

        #region 计算列属性
        /// <summary>
        /// 是否是计算列
        /// </summary>
        public bool IsComputed { get; set; }

        /// <summary>
        /// 计算列的定义
        /// </summary>
        public string ComputedDefinition { get; set; }

        /// <summary>
        /// 如果是计算列的话,是否是持久化存储的
        /// </summary>
        public bool? IsPersisted { get; set; }
        #endregion
    }
}
